﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Collections;
using MySQLStudio.ComponentModel;

namespace MySQLStudio.BusinessLogic
{
    public class ColumnCollection : CollectionBase, IBindingList, IList<Column>
    {
        private ListChangedEventArgs m_resetEvent = new ListChangedEventArgs(ListChangedType.Reset, -1);
        private ListChangedEventHandler m_listChanged;
        private ItemRemovedEventHandler m_itemRemoved;
                
        private IColumnsContainer m_container;

        public IColumnsContainer Container
        {
            get
            {
                return m_container;
            }
            internal set
            {
                m_container = value;

                foreach (Column column in this)
                {
                    column.Container = value;
                }
            }
        }

        public ColumnCollection()
            : base()
        {
        }

        public ColumnCollection(IColumnsContainer container)
            : base()
        {
            this.m_container = container;
        }

        public Column this[int index]
        {
            get
            {
                return (Column)base.List[index];
            }
            set
            {
                base.List[index] = value;
            }
        }

        // Events.
        public event ListChangedEventHandler ListChanged
        {
            add
            {
                m_listChanged += value;
            }
            remove
            {
                m_listChanged -= value;
            }
        }

        public event ItemRemovedEventHandler ItemRemoved
        {
            add
            {
                m_itemRemoved += value;
            }
            remove
            {
                m_itemRemoved -= value;
            }
        }

        public int Add(Column value)
        {
            value.ColumnChanged += new EventHandler<ColumnChangedEventArgs>(column_ColumnChanged);
            return base.List.Add(value);
        }

        void column_ColumnChanged(object sender, ColumnChangedEventArgs e)
        {
            //throw new NotImplementedException();
        }

        public Column AddNew()
        {
            Column column = (Column)((IBindingList)this).AddNew();

            column.ColumnChanged += new EventHandler<ColumnChangedEventArgs>(column_ColumnChanged);

            return column;
        }

        public void Remove(Column value)
        {
            value.ColumnChanged -= new EventHandler<ColumnChangedEventArgs>(column_ColumnChanged);

            base.List.Remove(value);
        }

        protected virtual void OnListChanged(ListChangedEventArgs e)
        {
            if (m_listChanged != null)
            {
                m_listChanged(this, e);
            }
        }

        protected virtual void OnItemRemoved(ItemRemovedEventArgs e)
        {
            if (m_itemRemoved != null)
            {
                m_itemRemoved(this, e);
            }
        }

        public void Insert(int index, Column column)
        {
            base.List.Insert(index, column);
        }

        protected override void OnClearComplete()
        {
            this.OnListChanged(this.m_resetEvent);
        }        

        protected override void OnInsertComplete(int index, object value)
        {
            Column column = (Column)value;
            column.ColumnChanged += new EventHandler<ColumnChangedEventArgs>(column_ColumnChanged);
            column.Container = this.m_container;

            this.OnListChanged(new ListChangedEventArgs(ListChangedType.ItemAdded, index));
        }        

        protected override void OnRemoveComplete(int index, object value)
        {
            Column column = (Column)value;
            column.ColumnChanged -= new EventHandler<ColumnChangedEventArgs>(column_ColumnChanged);            

            this.OnItemRemoved(new ItemRemovedEventArgs(index, (Column)value));
            this.OnListChanged(new ListChangedEventArgs(ListChangedType.ItemDeleted, index));

        }

        protected override void OnSetComplete(int index, object oldValue, object newValue)
        {
            if (oldValue != newValue)
            {
                Column oldColumn = (Column)oldValue;
                Column newColumn = (Column)newValue;

                oldColumn.ColumnChanged -= new EventHandler<ColumnChangedEventArgs>(column_ColumnChanged);                
                newColumn.ColumnChanged += new EventHandler<ColumnChangedEventArgs>(column_ColumnChanged);

                newColumn.Container = this.m_container;

                this.OnListChanged(new ListChangedEventArgs(ListChangedType.ItemAdded, index));
            }

        }

        #region IBindingList Members

        void IBindingList.AddIndex(PropertyDescriptor property)
        {
            throw new NotImplementedException();
        }

        object IBindingList.AddNew()
        {
            Column column = new Column();

            base.List.Add(column);

            return column;
        }

        bool IBindingList.AllowEdit
        {
            get
            {
                return true;
            }
        }

        bool IBindingList.AllowNew
        {
            get
            {
                return true;
            }
        }

        bool IBindingList.AllowRemove
        {
            get
            {
                return true;
            }
        }

        void IBindingList.ApplySort(PropertyDescriptor property, ListSortDirection direction)
        {
            throw new NotImplementedException();
        }

        int IBindingList.Find(PropertyDescriptor property, object key)
        {
            throw new NotImplementedException();
        }

        bool IBindingList.IsSorted
        {
            get { throw new NotImplementedException(); }
        }        

        void IBindingList.RemoveIndex(PropertyDescriptor property)
        {
            throw new NotImplementedException();
        }

        void IBindingList.RemoveSort()
        {
            throw new NotImplementedException();
        }

        ListSortDirection IBindingList.SortDirection
        {
            get { throw new NotImplementedException(); }
        }

        PropertyDescriptor IBindingList.SortProperty
        {
            get { throw new NotImplementedException(); }
        }

        bool IBindingList.SupportsChangeNotification
        {
            get
            {
                return true;
            }
        }

        bool IBindingList.SupportsSearching
        {
            get
            {
                return false;
            }
        }

        bool IBindingList.SupportsSorting
        {
            get
            {
                return false;
            }
        }

        #endregion

        internal void Commit()
        {
            foreach(Column column in this)
            {
                column.Commit();
            }
        }

        #region IList<Column> Members

        int IList<Column>.IndexOf(Column item)
        {
            for (int i = 0; i < this.Count; i++ )
            {
                if (this[i] == item)
                {
                    return i;
                }
            }

            return -1;
        }

        void IList<Column>.Insert(int index, Column item)
        {
            this.Insert(index, item);
        }

        void IList<Column>.RemoveAt(int index)
        {
            this.RemoveAt(index);
        }

        Column IList<Column>.this[int index]
        {
            get
            {
                return this[index];
            }
            set
            {
                this[index] = value;
            }
        }

        #endregion

        #region ICollection<Column> Members

        void ICollection<Column>.Add(Column item)
        {
            this.Add(item);
        }

        void ICollection<Column>.Clear()
        {
            this.Clear();
        }

        bool ICollection<Column>.Contains(Column item)
        {
            foreach (Column column in this)
            {
                if (column == item)
                {
                    return true;
                }
            }

            return false;
        }

        void ICollection<Column>.CopyTo(Column[] array, int arrayIndex)
        {
            if (arrayIndex < 0 || arrayIndex >= array.Length
                || arrayIndex + this.Count >= array.Length)
            {
                throw new IndexOutOfRangeException();
            }

            for (int i = 0; i < this.Count; i++)
            {
                array[i + arrayIndex] = this[i];
            }
        }

        int ICollection<Column>.Count
        {
            get
            {
                return this.Count;
            }
        }

        bool ICollection<Column>.IsReadOnly
        {
            get
            {
                return false;
            }
        }

        bool ICollection<Column>.Remove(Column item)
        {
            this.Remove(item);

            return true;
        }

        #endregion

        #region IEnumerable<Column> Members

        IEnumerator<Column> IEnumerable<Column>.GetEnumerator()
        {
            for (int i = 0; i < this.Count; i++)
            {
                yield return this[i];
            }
        }

        #endregion
    }
}
